var game = {
	// 数据、行、列、记录游戏状态、数据的初始值
	data : null,
	RN : 4,
	CN : 4,
	ovar : false,
	score : 0,

	// 游戏的进程
	start(){
		// data数据初始化
		// 生成一个二维数组，并给每一个值赋值为0
		this.data = [];
		for(var r = 0; r < this.RN; r++){
			this.data[r] = [];
			for(var c = 0; c < this.CN; c++){
				this.data[r][c] = 0;
			}
		}
		// 随机生成两个数据
		this.randomNum();
		this.randomNum();
		// 更新视图
		this.updateView();

		// 键盘事件  对应的上下左右事件的绑定
		// onkeydown事件的this指向Windows，需要修改为当前的this指向
		document.onkeydown = function (ever) {
			var e = event || window.event;//事件兼容性写法
			// 键盘的keycode值
			switch (event.keyCode) {
				case 37:
					// 左移
					this.moverLeft();
					break;
				case 38:
					// 上移
					this.moverUp();
					break;
				case 39:
					// 右移
					this.moverRight();
					break;
				case 40:
					// 下移
					this.moverDown();
					break;
			}
		}.bind(this);
		mytouch();
	},

	// 生成随机数函数
	randomNum(){
		while (true) {
			// 生成两个随机数
			var r = Math.random()*this.RN | 0;
			var c = Math.random()*this.CN | 0;
			// 判断当前值是否为0，为0添加一个值（2/4）
			if(this.data[r][c] == 0){
				this.data[r][c] = Math.random() > 0.3 ? 2 : 4;
				break;
			}
		}
	},
	// 游戏结束
	gameover(){
		// 游戏结束条件
			// 首先页面上全部非0，上下不相等，左右不相等
		// 页面还有空，上下相同、左右相同返回false
		for(var r = 0; r < this.RN; r++){
			for(var c = 0; c < this.CN; c++){
				if(this.data[r][c] == 0){
					return false;
				}
				// 判断当前一个和下一个是否相等，所以c就不用到最后一个
				if(c < this.CN - 1){
					if(this.data[r][c] == this.data[r][c+1]){
						return false;
					}
				}
				if(r < this.RN - 1){
					if(this.data[r][c] == this.data[r+1][c]){
						return false;
					}
				}
			}
		}
		return true;
	},

	// 更新视图函数
	updateView(){
		// 获取全部的id，设置为对应的this.data数值，样式
		for(var r = 0; r < this.RN; r++){
			for(var c = 0; c < this.CN; c++){
				// 获取页面上的id
				var div = document.getElementById('c' + r + c);
				// 当当前值不为0
				if(this.data[r][c] != 0){
					// 设置内容和样式
					div.innerHTML = this.data[r][c];
					div.className = 'cell n' + this.data[r][c];
				}else {
					// 清空当前元素在页面上的值，和初始样式
					div.innerHTML = '';
					div.className = 'cell';
				}
			}
		}
		// 获取页面上的分数元素
		var score = document.getElementById('score');
		// 设置分数
		score.innerHTML = this.score;
		// 接受返回值
		this.over = this.gameover();
		// 判断当this.over为true就为游戏结束
		if(this.over){
			// 获取遮荫层元素
			var div = document.getElementsByClassName('gameover')[0];
			// 显示遮荫层
			div.style.display = 'block';
			// 获取分数元素
			var score1 = document.getElementById('score1');
			// 设置分数
			score1.innerHTML = this.score;
		}
	},

	// 左移
	moverLeft(){
		// 左移前数组的值
		var data =  String(this.data);
		for(var r = 0; r < this.RN; r++){
			// 每一行的移动
			this.moveLeftInRow(r);
		}
		// 左移后数组的值
		var newData =  String(this.data);
		// 如果页面发生了改变，就增加一个随机数，然后再做更新视图
		if(newData != data){
			this.randomNum();
			this.updateView();
		}
	},

	// 每一行的左移
	moveLeftInRow(r){
		for(var c = 0; c < this.CN - 1; c++){
			// 接受返回值
			var next = this.getLeftNextInRow(r,c);
			// 如果为-1，也就是没有找到 直接结束循环
			if(next != -1){
				// 判断当前值是否为0，0移动，移动之后再从当前元素开始c--，相同的相加，移动后要清空被移动的元素
				if(this.data[r][c] == 0){
					// 给当前元素赋值
					this.data[r][c] = this.data[r][next];
					// 清空找到的元素
					this.data[r][next] = 0;
					// 在从当前位置开始
					c--;
				}else if (this.data[r][c] == this.data[r][next]) {
					// 相加
					this.data[r][c] *= 2;
					// 添加分数
					this.score += this.data[r][c];
					// 清空找到的元素
					this.data[r][next] = 0;
				}
			}else {
				// 结束循环
				break;
			}
		}
	},

	// 查找返回下一个不是0的数字下标，如果没有找到返回-1
	getLeftNextInRow(r,c){
		for (var i = c + 1;i < 4; i++) {
			if(this.data[r][i] != 0){
				return i;
			}
		}
		return -1;
	},

	// 右移
	moverRight(){
		// 右移前数组的值
		var data =  String(this.data);
		for(var r = 0; r < this.RN; r++){
			// 每一行的移动
			this.moveRightInRow(r);
		}
		// 右移后数组的值
		var newData =  String(this.data);
		// 如果页面发生了改变，就增加一个随机数，然后再做更新视图
		if(newData != data){
			this.randomNum();
			this.updateView();
		}
	},

	// 每一行的右移
	moveRightInRow(r){
		for(var c = this.CN - 1; c > 0; c--){
			// 接受返回值
			var next = this.getRightNextInRow(r,c);
			// 如果为-1，也就是没有找到 直接结束循环
			if(next != -1){
				// 判断当前值是否为0，0移动，移动之后再从当前元素开始c++，相同的相加，移动后要清空被移动的元素
				if(this.data[r][c] == 0){
					// 给当前元素赋值
					this.data[r][c] = this.data[r][next];
					// 清空找到的元素
					this.data[r][next] = 0;
					// 在从当前位置开始
					c++;
				}else if (this.data[r][c] == this.data[r][next]) {
					// 相加
					this.data[r][c] *= 2;
					// 添加分数
					this.score += this.data[r][c];
					// 清空找到的元素
					this.data[r][next] = 0;
				}
				
			}else {
				break;
			}
		}
	},

	// 查找返回前一个不是0的数字下标，如果没有返回-1
	getRightNextInRow(r,c){
		for (var i = c - 1;i >= 0; i--) {
			if(this.data[r][i] != 0){
				return i;
			}
		}
		return -1;
	},

	// 上移
	moverUp(){
		// 上移前数组的值
		var data =  String(this.data);
		for(var c = 0; c < this.CN; c++){
			// 每一列的移动
			this.moveUpInRow(c);
		}
		// 上移后数组的值
		var newData =  String(this.data);
		// 如果页面发生了改变，就增加一个随机数，然后再做更新视图
		if(newData != data){
			this.randomNum();
			this.updateView();
		}
	},

	// 每一行的上移
	moveUpInRow(c){
		for(var r = 0; r < this.RN - 1; r++){
			// 接受返回值
			var next = this.getUpNextInRow(r,c);
			// 如果为-1，也就是没有找到 直接结束循环
			if(next != -1){
				// 判断当前值是否为0，0移动，移动之后再从当前元素开始r--，相同的相加，移动后要清空被移动的元素
				if(this.data[r][c] == 0){
					// 给当前元素赋值
					this.data[r][c] = this.data[next][c];
					// 清空找到的元素
					this.data[next][c] = 0;
					// 在从当前位置开始
					r--;
				}else if (this.data[r][c] == this.data[next][c]) {
					// 相加
					this.data[r][c] *= 2;
					// 添加分数
					this.score += this.data[r][c];
					// 清空找到的元素
					this.data[next][c] = 0;
				}
				
			}else {
				break;
			}
		}
	},

	// 查找返回下一个不是0的数字下标，如果没有返回-1
	getUpNextInRow(r,c){
		for (var i = r + 1;i < 4; i++) {
			if(this.data[i][c] != 0){
				return i;
			}
		}
		return -1;
	},

	// 下移
	moverDown(){
		// 下移前数组的值
		var data =  String(this.data);
		for(var c = 0; c < this.CN; c++){
			// 每一列的移动
			this.moveDownInRow(c);
		}
		// 下移后数组的值
		var newData =  String(this.data);
		// 如果页面发生了改变，就增加一个随机数，然后再做更新视图
		if(newData != data){
			this.randomNum();
			this.updateView();
		}
	},

	// 每一行的下移
	moveDownInRow(c){
		for(var r = this.RN - 1; r > 0; r--){
			// 接受返回值
			var next = this.getDownNextInRow(r,c);
			// 如果为-1，也就是没有找到 直接结束循环
			if(next != -1){
				// 判断当前值是否为0，0移动，移动之后再从当前元素开始r++，相同的相加，移动后要清空被移动的元素
				if(this.data[r][c] == 0){
					// 给当前元素赋值
					this.data[r][c] = this.data[next][c];
					// 清空找到的元素
					this.data[next][c] = 0;
					// 在从当前位置开始
					r++;
				}else if (this.data[r][c] == this.data[next][c]) {
					// 相加
					this.data[r][c] *= 2;
					// 添加分数
					this.score += this.data[r][c];
					// 清空找到的元素
					this.data[next][c] = 0;
				}
				
			}else {
				break;
			}
		}
	},

	// 查找返回上一个不是0的数字下标，如果没有返回-1
	getDownNextInRow(r,c){
		for (var i = r - 1;i >= 0; i--) {
			if(this.data[i][c] != 0){
				return i;
			}
		}
		return -1;
	},

	// 再来一次
	onClick(){
		// 获取到遮荫层
		var div = document.getElementsByClassName('gameover')[0];
		// 隐藏
		div.style.display = 'none';
		// 清空分数
		this.score = 0;
		// 调用开始函数
		this.start();
	}
}

game.start();

// 移动端的app事件
function mytouch(){
	var startX,
	startY,
	endX,
	endY;

	// 手指放到屏幕上时触发
	document.addEventListener('touchstart',function(ever){
		// touches: 当前屏幕上所有手指的列表
		// pageX / pageY:触摸点相对于页面的位置
		startX = ever.touches[0].pageX;
		startY = ever.touches[0].pageY;
	})

	// 手指离开屏幕时触发
	document.addEventListener('touchend',function(ever){
		// changedTouches:涉及当前事件的手指的列表
		// pageX / pageY:触摸点相对于页面的位置
		endX = ever.changedTouches[0].pageX;
		endY = ever.changedTouches[0].pageY;
		// 距离相减
		var X = startX - endX;
		var Y = startY - endY;
		// 判断进入左右还是上下（谁大进谁）
		var abs = Math.abs(X) - Math.abs(Y);
		if(X > 0 && abs > 0){
			// 左移 
			game.moverLeft();
		}else if (X < 0 && abs > 0) {
			// 右移
			game.moverRight();
		}else if (Y > 0 && abs < 0) {
			// 上移
			game.moverUp();
		}else if (Y < 0 && abs < 0) {
			// 下移
			game.moverDown();
		}
	})
}
